package com.sparrow.resource.reader.impl;

import com.sparrow.common.excel.ExcelReader;
import com.sparrow.common.excel.bean.*;
import com.sparrow.resource.convert.ValueConverter;
import com.sparrow.resource.reader.ResourceReader;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * excel配置资源读取器
 */
public class ExcelResourceReader implements ResourceReader {
    /**
     * 类型定义的行数
     */
    private static int TYPE_ROW = 4;
    /**
     * 服务器字段命名的行数
     */
    private static int SERVER_DEF_ROW = 5;
    /**
     * excel bean 定义
     */
    private static ConcurrentHashMap<String, ExcelBeanDefinition> beanDefinitions = new ConcurrentHashMap<>();

    private ExcelReader excelReader = new ExcelReader();

    @Override
    public <T> List<T> read(File file, Class<? extends T> clazz) {
        return read(file.getAbsolutePath(), clazz);
    }

    public <T> List<T> read(String fileName, Class<? extends T> clazz) {
        List<T> list = new ArrayList<>();
        excelReader.read(fileName, excel -> {
            String className = clazz.getName();
            ExcelBeanDefinition beanDefinition = beanDefinitions.computeIfAbsent(className, k -> createBeanDefinition(clazz, excel));

            //解析字段信息
            for (ExcelSheet sheet : excel.getSheetList()) {
                String sheetName = sheet.getSheetName();
                Map<Integer, FieldInfo> colFields = beanDefinition.getSheetColFields().get(sheetName);
                if (colFields == null) {
                    continue;
                }
                Map<String, FieldInfo> nameFields = beanDefinition.getSheetNameFields().get(sheetName);
                if (nameFields == null) {
                    continue;
                }
                Map<String, Field> classFields = beanDefinition.getFields();
                for (ExcelRow row : sheet.getRows()) {
                    if (row.getRow() < SERVER_DEF_ROW) {
                        continue;
                    }

                    try {
                        //创建配置实例
                        T instance = clazz.newInstance();
                        //设置实例字段值
                        for (ExcelCol col : row.getCols()) {
                            if (col.getCol() <= 0) {
                                continue;
                            }
                            FieldInfo fieldInfo = colFields.get(col.getCol());
                            if (fieldInfo == null) {
                                continue;
                            }
                            String name = fieldInfo.getName();
                            if (name == null) {
                                continue;
                            }
                            Field field = classFields.get(name);
                            //将配置字符串值 转换为 实例字段需要的类型值
                            Object obj = ValueConverter.convertVal(name, col.getVal(), fieldInfo.getType(), field);
                            //调用set方法设置
                            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, clazz);
                            Method writeMethod = propertyDescriptor.getWriteMethod();
                            writeMethod.invoke(instance, obj);
                        }
                        list.add(instance);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        return list;
    }

    private <T> ExcelBeanDefinition createBeanDefinition(Class<? extends T> clazz, Excel excel) {
        //解析字段信息
        Map<String, Map<Integer, FieldInfo>> sheetColFields = new HashMap<>();
        Map<String, Map<String, FieldInfo>> sheetNameFields = new HashMap<>();
        for (ExcelSheet sheet : excel.getSheetList()) {
            if (sheet.getRows().size() < SERVER_DEF_ROW) {
                continue;
            }
            ExcelCol[] fieldNameCols = sheet.getRows().get(SERVER_DEF_ROW - 1).getCols();
            if (fieldNameCols == null || fieldNameCols.length == 0) {
                continue;
            }
            if (!fieldNameCols[0].getVal().equals("SERVER")) {
                continue;
            }
            Map<Integer, FieldInfo> colFields = sheetColFields.computeIfAbsent(sheet.getSheetName(), k -> new HashMap<>());
            Map<String, FieldInfo> nameFields = sheetNameFields.computeIfAbsent(sheet.getSheetName(), k -> new HashMap<>());
            //类型映射 int string等
            ExcelCol[] typeCols = sheet.getRows().get(TYPE_ROW - 1).getCols();
            for (ExcelCol col : typeCols) {
                if (col.getCol() <= 0) {
                    continue;
                }
                FieldInfo fieldInfo = new FieldInfo();
                fieldInfo.setType(col.getVal());
                colFields.put(col.getCol(), fieldInfo);
            }

            for (ExcelCol col : fieldNameCols) {
                if (col.getCol() <= 0) {
                    continue;
                }
                FieldInfo fieldInfo = colFields.get(col.getCol());
                fieldInfo.setName(col.getVal());
                nameFields.put(fieldInfo.getName(), fieldInfo);
            }
        }

        Map<String, Field> classFields = new HashMap<>();
        for (Field f : clazz.getDeclaredFields()) {
            classFields.put(f.getName(), f);
        }
        return new ExcelBeanDefinition(clazz.getName(), sheetColFields, sheetNameFields, classFields);
    }




}
